package cn.bulgat.spring.web.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * 密码学工具类
 */
public class CryptoUtils {

    private static final SecureRandom random = new SecureRandom();
    private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();

    /**
     * 生成指定字节长度的随机盐值（Base64编码）
     * @param byteLength 盐值的字节长度（建议至少16字节）
     * @return Base64编码的盐值字符串
     */
    public static String generateSalt(int byteLength) {
        byte[] bytes = new byte[byteLength];
        random.nextBytes(bytes);
        return Base64.getEncoder().encodeToString(bytes);
    }
    /**
     * 使用SHA-256算法进行加密（盐值 + 密码）
     * @param password 用户密码明文
     * @param salt     Base64编码的盐值字符串
     * @return 十六进制格式的哈希值
     */
    public static String sha256WithSalt(String password, String salt) {
        try {
            // 将Base64盐值转换为原始字节
            byte[] saltBytes = Base64.getDecoder().decode(salt);

            // 将密码字符串转换为UTF-8字节
            byte[] passwordBytes = password.getBytes(java.nio.charset.StandardCharsets.UTF_8);

            // 合并盐值和密码字节
            byte[] combinedBytes = new byte[saltBytes.length + passwordBytes.length];
            System.arraycopy(saltBytes, 0, combinedBytes, 0, saltBytes.length);
            System.arraycopy(passwordBytes, 0, combinedBytes, saltBytes.length, passwordBytes.length);

            // 计算SHA-256哈希
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = digest.digest(combinedBytes);

            // 返回十六进制字符串
            return bytesToHex(hashBytes);
        } catch (NoSuchAlgorithmException e) {
            // SHA-256是Java标准算法，理论上不会触发此异常
            throw new RuntimeException("SHA-256 algorithm not available", e);
        }
    }
    /**
     * 验证密码是否匹配
     * @param password      用户输入的密码
     * @param salt          注册时生成的盐值
     * @param expectedHash  注册时存储的哈希值
     * @return 验证结果
     */
    public static boolean verifyPassword(String password, String salt, String expectedHash) {
        String actualHash = sha256WithSalt(password, salt);
        return MessageDigest.isEqual(
                hexToBytes(expectedHash),
                hexToBytes(actualHash)
        );
    }

    /**
     * 将字节数组转换为十六进制字符串（小写）
     */
    private static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int i = 0; i < bytes.length; i++) {
            int v = bytes[i] & 0xFF;
            hexChars[i * 2] = HEX_ARRAY[v >>> 4];
            hexChars[i * 2 + 1] = HEX_ARRAY[v & 0x0F];
        }
        return new String(hexChars);
    }

    /**
     * 将十六进制字符串转换为字节数组
     */
    private static byte[] hexToBytes(String hex) {
        int len = hex.length();
        if (len % 2 != 0) {
            throw new IllegalArgumentException("Invalid hex string");
        }
        byte[] bytes = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            int high = Character.digit(hex.charAt(i), 16) << 4;
            int low = Character.digit(hex.charAt(i + 1), 16);
            bytes[i / 2] = (byte) (high | low);
        }
        return bytes;
    }
}
